bitkeeper revision 1.786 (4051a33dlWQlrVd1OVpwmHvW8Lp8Zw)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 12 Mar 2004 11:47:09 +0000 (11:47 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 12 Mar 2004 11:47:09 +0000 (11:47 +0000)
serial.h, serial.c, traps.c, pdb-stub.c:
  Fix serial-char receive for PDB.

xen/arch/i386/pdb-stub.c
xen/arch/i386/traps.c
xen/drivers/char/serial.c
xen/include/xeno/serial.h

index 3f905b3f056d4ee1e2ef87c4b04b1f46915900d7..3184c7e62990e5090738e70a38d67512bbdea9ca 100644 (file)
@@ -32,11 +32,6 @@ void pdb_put_packet (unsigned char *buffer, int ack);
 int pdb_initialized = 0;
 static int pdb_serhnd      = -1;
 
-#define RX_SIZE 32
-#define RX_MASK(_i) ((_i)&(RX_SIZE-1))
-static unsigned int rx_cons = 0, rx_prod = 0;
-static unsigned char rx_ring[RX_RING_SIZE];
-
 static inline void pdb_put_char(unsigned char c)
 {
     serial_putc(pdb_serhnd, c);
@@ -44,15 +39,7 @@ static inline void pdb_put_char(unsigned char c)
 
 static inline unsigned char pdb_get_char(void)
 {
-    while ( rx_cons == rx_prod )
-        barrier();
-    return rx_ring[RX_MASK(rx_cons++)];
-}
-
-static void pdb_rx_char(unsigned char c, struct pt_regs *regs)
-{
-    if ( (rx_prod - rx_cons) != RX_SIZE )
-        rx_ring[RX_MASK(rx_prod++)] = c;
+    return serial_getc(pdb_serhnd);
 }
 
 static volatile int mem_err = 0;
@@ -844,8 +831,6 @@ void initialize_pdb()
         return;
     }
 
-    serial_set_rx_handler(pdb_serhnd, pdb_rx_char);
-
     printk("Initialised pervasive debugger (PDB) on port %s\n", opt_pdb);
 
     /* Acknowledge any spurious GDB packets. */
index 00a8fd2b52e0741968c443e24b2b98a79cb732ab..f71ce60d570317a1188f5a3c0e1cb15d5c4dc7da 100644 (file)
@@ -196,8 +196,6 @@ static inline void do_trap(int trapnr, char *str,
     trap_info_t *ti;
     unsigned long fixup;
 
-    __sti();
-
     if (!(regs->xcs & 3))
         goto fault_in_hypervisor;
 
@@ -259,8 +257,6 @@ asmlinkage void do_int3(struct pt_regs *regs, long error_code)
     struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
     trap_info_t *ti;
 
-    __sti();
-
     if ( (regs->xcs & 3) != 3 )
     {
         if ( pdb_handle_exception(3, regs) == 0 )
@@ -327,8 +323,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
 
     __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
 
-    __sti();
-
     if ( unlikely(addr >= LDT_VIRT_START) && 
          (addr < (LDT_VIRT_START + (p->mm.ldt_ents*LDT_ENTRY_SIZE))) )
     {
@@ -396,8 +390,6 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
     trap_info_t *ti;
     unsigned long fixup;
 
-    __sti();
-
     /* Badness if error in ring 0, or result of an interrupt. */
     if ( !(regs->xcs & 3) || (error_code & 1) )
         goto gp_in_kernel;
@@ -506,8 +498,6 @@ asmlinkage void math_state_restore(struct pt_regs *regs, long error_code)
     /* Prevent recursion. */
     clts();
 
-    __sti();
-
     if ( !test_bit(PF_USEDFPU, &current->flags) )
     {
         if ( test_bit(PF_DONEFPUINIT, &current->flags) )
@@ -532,8 +522,6 @@ asmlinkage void do_debug_orig(struct pt_regs *regs, long error_code)
     struct task_struct *tsk = current;
     struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
 
-    __sti();
-
     __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
 
     /* Mask out spurious debug traps due to lazy DR7 setting */
@@ -580,8 +568,6 @@ asmlinkage void do_debug(struct pt_regs *regs, long error_code)
         return;
     }
 
-    __sti();
-
     __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
     if ( (condition & (1 << 14)) != (1 << 14) )
         printk("\nwarning: debug trap w/o BS bit [0x%x]\n\n", condition);
index ff5d3d1e4ce0fc386f36c147c747656693d2669b..ad8a4a27023d78106d0a4bc82fd7b37cef5a4f40 100644 (file)
 #define PARITY_MARK     (5<<3)
 #define PARITY_SPACE    (7<<3)
 
+#define RXBUFSZ 32
+#define MASK_RXBUF_IDX(_i) ((_i)&(RXBUFSZ-1))
 typedef struct {
-    int          baud, data_bits, parity, stop_bits, io_base, irq;
-    serial_rx_fn rx_lo, rx_hi, rx;
-    spinlock_t   lock;
+    int           baud, data_bits, parity, stop_bits, io_base, irq;
+    serial_rx_fn  rx_lo, rx_hi, rx;
+    spinlock_t    lock;
+    unsigned char rxbuf[RXBUFSZ];
+    unsigned int  rxbufp, rxbufc;
 } uart_t;
 
 static uart_t com[2] = {
@@ -103,6 +107,7 @@ static void uart_rx(uart_t *uart, struct pt_regs *regs)
     /*
      * No need for the uart spinlock here. Only the uart's own interrupt
      * handler will read from the RBR and the handler isn't reentrant.
+     * Calls to serial_getc() will disable this handler before proceeding.
      */
     while ( inb(uart->io_base + LSR) & LSR_DR )
     {
@@ -113,6 +118,8 @@ static void uart_rx(uart_t *uart, struct pt_regs *regs)
             uart->rx_hi(c&0x7f, regs);
         else if ( !(c & 0x80) && (uart->rx_lo != NULL) )
             uart->rx_lo(c&0x7f, regs);
+        else if ( (uart->rxbufp - uart->rxbufc) != RXBUFSZ )
+            uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufp++)] = c;            
     }
 }
 
@@ -396,3 +403,59 @@ void serial_puts(int handle, const unsigned char *s)
 
     spin_unlock_irqrestore(&uart->lock, flags);
 }
+
+/* Returns TRUE if given character (*pc) matches the serial handle. */
+static int byte_matches(int handle, unsigned char *pc)
+{
+    if ( !(handle & SERHND_HI) )
+    {
+        if ( !(handle & SERHND_LO) || !(*pc & 0x80) )
+            return 1;
+    }
+    else if ( *pc & 0x80 )
+    {
+        *pc &= 0x7f;
+        return 1;
+    }
+    return 0;
+}
+
+unsigned char serial_getc(int handle)
+{
+    uart_t *uart = &com[handle & SERHND_IDX];
+    unsigned char c;
+    unsigned long flags;
+
+    spin_lock_irqsave(&uart->lock, flags);
+
+    while ( uart->rxbufp != uart->rxbufc )
+    {
+        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
+        if ( byte_matches(handle, &c) )
+            goto out;
+    }
+    
+    disable_irq(uart->irq);
+    
+    /* disable_irq() may have raced execution of uart_rx(). */
+    while ( uart->rxbufp != uart->rxbufc )
+    {
+        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
+        if ( byte_matches(handle, &c) )
+            goto enable_and_out;
+    }
+
+    /* We now wait for the UART to receive a suitable character. */
+    do {
+        while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
+            barrier();
+        c = inb(uart->io_base + RBR);
+    }
+    while ( !byte_matches(handle, &c) );
+    
+ enable_and_out:
+    enable_irq(uart->irq);
+ out:
+    spin_unlock_irqrestore(&uart->lock, flags);
+    return c;
+}
index c24f0c665f16eb0b17228dd1adef5b1733e53b64..3640fd036f4f429b0b743ffdc0bd0748365bdebf 100644 (file)
@@ -36,4 +36,11 @@ void serial_putc(int handle, unsigned char c);
 /* Transmit a NULL-terminated string via the specified COM port. */
 void serial_puts(int handle, const unsigned char *s);
 
+/*
+ * An alternative to registering a character-receive hook. This function
+ * will not return until a character is available. It can safely be
+ * called with interrupts disabled.
+ */
+unsigned char serial_getc(int handle);
+
 #endif /* __XEN_SERIAL_H__ */